﻿using System;
using Deer;
using Deer.Log;

namespace Telex;

public abstract class ABuilder<TBuilder, THost> where TBuilder : class where THost : IRpcService
{
    protected string secretkey;
    protected string cluster;
    protected string service;
    
    protected ILogger logger;
    internal ProtocolMap protocolMap = new();
    protected ActionAsync<RpcHost, ServiceKind> onChannelActive;
    protected ActionAsync<RpcHost, ServiceKind> onChannelInactive;
    
    public TBuilder ConfigureSecretkey(string secretkey)
    {
        if (string.IsNullOrEmpty(secretkey))
        {
            throw new ArgumentNullException(nameof(secretkey));
        }

        this.secretkey = secretkey;
        
        return this as TBuilder;
    }

    public TBuilder ConfigureLogger(ILogger logger)
    {
        if (logger == null)
        {
            throw new ArgumentNullException(nameof(logger));
        }

        this.logger = logger;
        return this as TBuilder;
    }

    public TBuilder AddSendProtocol(uint protocolId, SendProtocolDelegate func)
    {
        if (!this.protocolMap.sendProtocolMap.TryAdd(protocolId, func))
        {
            throw new Exception("Agreements that already exist. protocolId:" + protocolId);
        }

        return this as TBuilder;
    }
    
    public TBuilder AddCallProtocol(uint protocolId, CallProtocolDelegate func)
    {
        if (!this.protocolMap.callProtocolMap.TryAdd(protocolId, func))
        {
            throw new Exception("Agreements that already exist. protocolId:" + protocolId);
        }

        return this as TBuilder;
    }
    
    public TBuilder ConfigureChannelActive(ActionAsync<RpcHost, ServiceKind> func)
    {
        if (func == null)
        {
            throw new ArgumentNullException(nameof(func));
        }

        this.onChannelActive = func;
        return this as TBuilder;
    }

    public TBuilder ConfigureChannelInactive(ActionAsync<RpcHost, ServiceKind> func)
    {
        if (func == null)
        {
            throw new ArgumentNullException(nameof(func));
        }

        this.onChannelInactive = func;
        return this as TBuilder;
    }

    public abstract THost Build();
}